package web.newcrawler;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.lou.simhasher.SimHasher;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.downloader.selenium.SeleniumDownloader;
import us.codecraft.webmagic.scheduler.BloomFilterDuplicateRemover;
import us.codecraft.webmagic.scheduler.QueueScheduler;
import utils.OperatorUtil;
import utils.UrlUtils;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/*import com.lou.simhasher.SimHasher;*/

public class CrawlerLoginAction extends ActionSupport {
    private String url;
    private String username;
    private String password;
    private String cookies;

    private HttpSession session = ServletActionContext.getRequest().getSession();


    //解析页面的方法
    public String analysis() {
        System.out.println("进入了解析的方法");
        //地址格式化
        url = UrlUtils.getRequestUrl(url);
        //创建Selenium对象作为webmagic的访问对象
        SeleniumDownloader seleniumDownloader = new SeleniumDownloader();

        //创建自定义的页面持久化类
        DataPipeline dataPipeline = new DataPipeline();
        //使用webmagic的引导对象
        Spider.create(new AnalyProcessor())
                .addUrl(url)
                .setDownloader(seleniumDownloader)
//                .addPipeline(dataPipeline)
                .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(10000000)))
                .thread(10)
                .run();
        return "analysis";
//        return NONE;
    }

    //手动添加cookie的方法
    public String addCookies() {
        System.out.println("调用到了方法");
        System.out.println("封装的参数有:" + cookies);
        //1.把cookies的Json串转化成Json数组对象
        JsonParser parser = new JsonParser();
        JsonArray jsonArray = parser.parse(cookies).getAsJsonArray();

        Set<Cookie> cookieSet = new HashSet<>();
        Gson gson = new Gson();
        //2.遍历数组对象,把每一条json语句封装成Cookie对象
        for (JsonElement element : jsonArray) {
            Cookie cookie = gson.fromJson(element, Cookie.class);
            cookieSet.add(cookie);
        }
        //3.存入session域
        session.setAttribute("cookies", cookieSet);

        return NONE;
    }


    //模拟登录的方法
    public String login() throws IOException {
        //拿到了数据,可以进行模拟登录了
        //获取到response对象
        HttpServletResponse response = ServletActionContext.getResponse();
        response.setCharacterEncoding("utf-8");

        //1.把url地址格式化
        url = UrlUtils.getRequestUrl(url);

        //2.创建用于模拟登录的selenium对象
        //2.1创建WebDriver对象
        WebDriver webDriver = getWebDriver();

        //2.2使用WebDriver对象访问url
        OperatorUtil.open(webDriver, url);
        //2.3等待页面加载
        OperatorUtil.waitTime(2000);

        //获取页面源码,进行第4步的登录成功判断
        String source1 = webDriver.getPageSource();

        //2.4获取当前的访问到的url地址
        String currentUrl = webDriver.getCurrentUrl();

        //3.模拟登录
        //3.1找到页面中的登录表单下的所有可输入的input
        List<WebElement> inputList =
                ((ChromeDriver) webDriver).findElementsByCssSelector("form input");
        List<WebElement> hiddenInputs =
                ((ChromeDriver) webDriver).findElementsByCssSelector("form input[type" +
                        "=hidden]");
        //3.2把数据填入
        inputList.get(0).sendKeys(this.username);
        inputList.get(1).sendKeys(this.password);
        //3.3寻找登录的按钮
        WebElement submit = null;
        if (inputList.size() >= 3) {
            //说明页面用的是<input type="submit">
            //通常认为提交按钮是最后一个
            submit = inputList.get(inputList.size() - 1);
        } else {
            //说明页面用的是<button type="submit">
            submit = ((ChromeDriver) webDriver).findElementByCssSelector("form " +
                    "button[type*='submit']");
        }
        //3.4模拟登录按钮的点击操作
        submit.click();

        //等待页面加载
        OperatorUtil.waitTime(2000);
        String source2 = webDriver.getPageSource();
        //4.1验证是否登录成功
        //比较两页面源码的相似度,使用simhasher
        SimHasher hasher1 = new SimHasher(source1);
        SimHasher hasher2 = new SimHasher(source2);
        if (hasher1.getHammingDistance(hasher2.getSignature()) <= 2) {
            //海明距离在0-2之间认为是一样的,即登录失败
            response.getWriter().write("模拟登录失败,请检查用户名密码是否出错");
        } else {
            //否则认为登录成功
            session.setAttribute("cookies", webDriver.manage().getCookies());
            webDriver.close();
            response.getWriter().write("模拟登录成功,请点击解析");
        }
        return NONE;
    }


    private WebDriver getWebDriver() {
        //发布时打开
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless");
        options.addArguments("--disable-gpu");
        return new ChromeDriver(options);
        //测试时打开
//        return new ChromeDriver();
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getCookies() {
        return cookies;
    }

    public void setCookies(String cookies) {
        this.cookies = cookies;
    }
}
